# ===============================================
# PowerShell v2 Compatible Named Pipe Client
# Compatible with both PowerShell v2 and v3+
# ===============================================

param(
    [string]$PipeName = "UnityWpfPipe",
    [string]$ServerName = ".",
    [int]$TimeoutMs = 10000
)

# Check PowerShell version
$PSVersion = $PSVersionTable.PSVersion.Major
Write-Host "PowerShell Version: $PSVersion" -ForegroundColor Cyan

if ($PSVersion -lt 2) {
    Write-Host "Error: PowerShell v2 or higher required" -ForegroundColor Red
    exit 1
}

Write-Host "=== PowerShell v$PSVersion Named Pipe Client ===" -ForegroundColor Cyan
Write-Host "Pipe Name: $PipeName" -ForegroundColor White
Write-Host "Server: $ServerName" -ForegroundColor White
Write-Host "Connection Timeout: ${TimeoutMs}ms" -ForegroundColor White
Write-Host ""

# Global variables
$script:pipeClient = $null
$script:streamWriter = $null
$script:streamReader = $null
$script:isConnected = $false

function Connect-ToPipeV2 {
    Write-Host "Connecting to pipe (PowerShell v2 mode)..." -ForegroundColor Yellow
    
    try {
        # Load required assemblies for v2 compatibility
        Add-Type -AssemblyName System.Core
        
        # Create pipe client - v2 compatible way
        $script:pipeClient = New-Object System.IO.Pipes.NamedPipeClientStream($ServerName, $PipeName)
        
        # Connect with timeout - v2 compatible method
        $script:pipeClient.Connect($TimeoutMs)
        $script:isConnected = $true
        
        # Create streams - v2 compatible
        $script:streamWriter = New-Object System.IO.StreamWriter($script:pipeClient)
        $script:streamWriter.AutoFlush = $true
        $script:streamReader = New-Object System.IO.StreamReader($script:pipeClient)
        
        Write-Host "✓ Successfully connected to pipe!" -ForegroundColor Green
        Write-Host "Connection Status: $($script:pipeClient.IsConnected)" -ForegroundColor Green
        Write-Host ""
        
        # Try to read welcome message (with timeout)
        $welcomeRead = $false
        $attempts = 0
        while (-not $welcomeRead -and $attempts -lt 10) {
            if ($script:streamReader.Peek() -ne -1) {
                $welcomeMessage = $script:streamReader.ReadLine()
                if ($welcomeMessage) {
                    Write-Host " $welcomeMessage" -ForegroundColor Green
                    $welcomeRead = $true
                }
            }
            Start-Sleep -Milliseconds 100
            $attempts++
        }
        
        return $true
    }
    catch {
        Write-Host "✗ Connection failed: $($_.Exception.Message)" -ForegroundColor Red
        Write-Host "Error Details: $($_.Exception.GetType().Name)" -ForegroundColor Red
        return $false
    }
}

function Send-MessageV2 {
    param([string]$Message)
    
    if (-not $script:isConnected -or -not $script:pipeClient.IsConnected) {
        Write-Host "✗ Connection lost, cannot send message" -ForegroundColor Red
        return $false
    }
    
    try {
        $script:streamWriter.WriteLine($Message)
        $script:streamWriter.Flush()  # Explicit flush for v2 compatibility
        Write-Host "→ Sent: '$Message'" -ForegroundColor Green
        
        # Try to read response immediately (v2 compatible way)
        $responseReceived = $false
        $attempts = 0
        while (-not $responseReceived -and $attempts -lt 20) {
            if ($script:pipeClient.IsConnected -and $script:streamReader.Peek() -ne -1) {
                $response = $script:streamReader.ReadLine()
                if ($response) {
                    # Display response with appropriate formatting
                    if ($response.StartsWith("Echo:")) {
                        Write-Host "$response" -ForegroundColor Blue
                    }
                    elseif ($response -eq "pong") {
                        Write-Host "Server: $response" -ForegroundColor Magenta
                    }
                    elseif ($response.StartsWith("Server time:")) {
                        Write-Host "$response" -ForegroundColor Cyan
                    }
                    elseif ($response -eq "Goodbye!") {
                        Write-Host "$response" -ForegroundColor Yellow
                    }
                    else {
                        Write-Host "Server: $response" -ForegroundColor White
                    }
                    $responseReceived = $true
                }
            }
            Start-Sleep -Milliseconds 50
            $attempts++
        }
        
        return $true
    }
    catch {
        Write-Host "✗ Failed to send message: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
}

function Test-ConnectionV2 {
    if ($script:pipeClient -and $script:isConnected) {
        try {
            $status = $script:pipeClient.IsConnected
            Write-Host "Connection Status: $status" -ForegroundColor $(if($status){"Green"}else{"Red"})
            
            if ($status) {
                # v2 compatible way to get pipe info
                Write-Host "Pipe Direction: $($script:pipeClient.PipeTransmissionMode)" -ForegroundColor Gray
            }
            return $status
        }
        catch {
            Write-Host "Connection Status: Error checking - $($_.Exception.Message)" -ForegroundColor Red
            return $false
        }
    } else {
        Write-Host "Connection Status: Not Connected" -ForegroundColor Red
        return $false
    }
}

function Disconnect-FromPipeV2 {
    Write-Host "Closing connection..." -ForegroundColor Yellow
    
    # Send disconnect command to server
    if ($script:isConnected -and $script:streamWriter) {
        try {
            $script:streamWriter.WriteLine("disconnect")
            $script:streamWriter.Flush()
            Start-Sleep -Milliseconds 300  # Give server time to respond
        }
        catch {
            # Ignore errors during disconnect
        }
    }
    
    # Clean up resources - v2 compatible way
    if ($script:streamWriter) {
        try { $script:streamWriter.Close() } catch { }
        try { $script:streamWriter.Dispose() } catch { }
        $script:streamWriter = $null
    }
    
    if ($script:streamReader) {
        try { $script:streamReader.Close() } catch { }
        try { $script:streamReader.Dispose() } catch { }
        $script:streamReader = $null
    }
    
    if ($script:pipeClient) {
        try { $script:pipeClient.Close() } catch { }
        try { $script:pipeClient.Dispose() } catch { }
        $script:pipeClient = $null
    }
    
    $script:isConnected = $false
    Write-Host "✓ Connection closed" -ForegroundColor Green
}

function Show-HelpV2 {
    Write-Host ""
    Write-Host "Available Commands (PowerShell v$PSVersion):" -ForegroundColor Cyan
    Write-Host "  send <message>   - Send message to server"
    Write-Host "  ping             - Test server with ping"
    Write-Host "  time             - Get server time"
    Write-Host "  status           - Check connection status"
    Write-Host "  reconnect        - Reconnect to server"
    Write-Host "  help             - Show this help"
    Write-Host "  exit/quit        - Exit program"
    Write-Host ""
    Write-Host "Note: PowerShell v2 mode - responses read immediately after sending" -ForegroundColor Yellow
    Write-Host ""
}

function Test-PowerShellCompatibility {
    Write-Host "Testing PowerShell compatibility..." -ForegroundColor Yellow
    
    # Test .NET assemblies
    try {
        Add-Type -AssemblyName System.Core
        Write-Host "✓ System.Core assembly loaded" -ForegroundColor Green
    }
    catch {
        Write-Host "✗ Failed to load System.Core: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
    
    # Test Named Pipe classes
    try {
        $testPipe = New-Object System.IO.Pipes.NamedPipeClientStream(".", "TestPipe")
        $testPipe.Dispose()
        Write-Host "✓ Named Pipe classes available" -ForegroundColor Green
    }
    catch {
        Write-Host "✗ Named Pipe classes not available: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
    
    Write-Host "✓ PowerShell compatibility check passed" -ForegroundColor Green
    return $true
}

# Main program logic
try {
    # Test compatibility first
    if (-not (Test-PowerShellCompatibility)) {
        Write-Host "Compatibility check failed. Exiting..." -ForegroundColor Red
        exit 1
    }
    
    # Attempt to connect
    if (-not (Connect-ToPipeV2)) {
        Write-Host ""
        Write-Host "Failed to connect. Please ensure:" -ForegroundColor Yellow
        Write-Host "  1. C# Named Pipe Server is running" -ForegroundColor Yellow
        Write-Host "  2. Pipe name matches: $PipeName" -ForegroundColor Yellow
        Write-Host "  3. PowerShell has required permissions" -ForegroundColor Yellow
        Write-Host "  4. .NET Framework 3.5+ is installed" -ForegroundColor Yellow
        exit 1
    }
    
    # Show help
    Show-HelpV2
    
    # Main interactive loop
    while ($true) {
        $userInput = Read-Host "PipeClient-v$PSVersion"
        
        if ([string]::IsNullOrWhiteSpace($userInput)) {
            continue
        }
        
        $parts = $userInput.Trim().Split(' ', 2)
        $command = $parts[0].ToLower()
        $message = if ($parts.Length -gt 1) { $parts[1] } else { "" }
        
        switch ($command) {
            "exit" { 
                break 
            }
            "quit" { 
                break 
            }
            "help" {
                Show-HelpV2
            }
            "status" {
                Test-ConnectionV2
            }
            "reconnect" {
                Disconnect-FromPipeV2
                Start-Sleep -Milliseconds 1000
                Connect-ToPipeV2
            }
            "send" {
                if ([string]::IsNullOrWhiteSpace($message)) {
                    Write-Host "Please provide message to send: send <message>" -ForegroundColor Yellow
                } else {
                    Send-MessageV2 $message
                }
            }
            "ping" {
                Send-MessageV2 "ping"
            }
            "time" {
                Send-MessageV2 "time"
            }
            default {
                # Send input directly as message
                Send-MessageV2 $userInput
            }
        }
        
        # Check connection status
        if ($script:isConnected -and $script:pipeClient -and -not $script:pipeClient.IsConnected) {
            Write-Host "⚠ Detected connection lost" -ForegroundColor Yellow
            $script:isConnected = $false
        }
    }
}
catch [System.TimeoutException] {
    Write-Host ""
    Write-Host "✗ Connection timeout!" -ForegroundColor Red
    Write-Host "This may be due to PowerShell version compatibility issues." -ForegroundColor Yellow
}
catch [System.IO.IOException] {
    Write-Host ""
    Write-Host "✗ IO Error: $($_.Exception.Message)" -ForegroundColor Red
}
catch {
    Write-Host ""
    Write-Host "✗ Error: $($_.Exception.Message)" -ForegroundColor Red
    Write-Host "Error Type: $($_.Exception.GetType().Name)" -ForegroundColor Red
    Write-Host ""
    Write-Host "Possible solutions:" -ForegroundColor Yellow
    Write-Host "  1. Try running as Administrator" -ForegroundColor Yellow
    Write-Host "  2. Ensure .NET Framework 3.5+ is installed" -ForegroundColor Yellow
    Write-Host "  3. Try PowerShell v3+ if available" -ForegroundColor Yellow
}
finally {
    Disconnect-FromPipeV2
    Write-Host ""
    Write-Host "Program exited (PowerShell v$PSVersion)" -ForegroundColor Cyan
}
